from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram import Client
from utils.sql import db
from utils.logger import logger
import re

'''
Плагин для обработки состояний пользователя
'''

# EDIT BALANCE
async def set_account_balance(client, message, state):
    user_id = message.chat.id
    bot_message_id = db.get_user_last_bot_message_id(user_id)
    balance = message.text
    account_id = re.search(r'set_balance.*', state).group(0)[12:]

    try:
        balance = float(message.text)
    except:
        try:
            await Client.edit_message_text(client, user_id, bot_message_id,
                text="\n\n💢 Ой, для баланса можно использовать только цифры 😔", reply_markup=old_message.reply_markup)
            return
        except:
            return
    db.set_balance(account_id, balance)
    db.set_state(user_id, "work")
    await Client.edit_message_text(client, chat_id=user_id, message_id=bot_message_id,
        text=f"☺️ Поздравляю! Новый баланс счета: <b>{balance}₽</b>", 
        reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Назад", callback_data=f"account-edit|{account_id}")]]))
    logger.info(f"SUCCESS! user_id:{user_id} balance:{balance}")

# SET ACCOUNT ALIASES
async def set_account_aliases(client, message, state):
    user_id = message.chat.id
    bot_message_id = db.get_user_last_bot_message_id(user_id)
    if message.text is None or len(message.text) > 20:
        await Client.edit_message_text(client, user_id, bot_message_id,
            text="💢 Ой, для алиасов можно использовать только короткий текст 😔\n\nПопробуй написать алиасы еще раз")
        return
    account_id = re.search(r'set_aliases.*', state).group(0)[12:]
    aliases = re.sub(r"\d+", "", message.text, flags=re.UNICODE)

    db.edit_account_aliases(account_id, aliases)
    db.set_state(user_id, "work")
    await Client.edit_message_text(client, chat_id=user_id, message_id=bot_message_id,
        text=f"☺️ Поздравляю! Новые алиасы счета: <b>{aliases}</b>", 
        reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Назад", callback_data=f"account-edit|{account_id}")]]))
    logger.info(f"SUCCESS! user_id:{user_id} aliases:{aliases}")

# SET ACCOUNT NAME
async def set_account_name(client, message, state):
    user_id = message.chat.id
    bot_message_id = db.get_user_last_bot_message_id(user_id)
    full_name = message.text
    account_id = re.search(r'set_name.*', state).group(0)[9:]

    if full_name is None or len(full_name) > 20:
        await Client.edit_message_text(client, user_id, bot_message_id,
            text="💢 Ой, для имени можно использовать только короткий текст 😔\n\nПопробуй другое имя")
        return
    
    db.edit_account_full_name(account_id, full_name)
    db.set_state(user_id, "work")
    await Client.edit_message_text(client, chat_id=user_id, message_id=bot_message_id,
        text=f"☺️ Поздравляю! Новое имя счета: <b>{full_name}</b>", 
        reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Назад", callback_data=f"account-edit|{account_id}")]]))
    logger.info(f"SUCCESS! user_id:{user_id} full_name:{full_name}")

# CREATE ACCOUNT
async def create_account(client, message, state, callback=None):
    '''
    Создает новый счет
    '''
    user_id = message.chat.id
    logger.info(f"INIT user_id:{user_id}")
    if callback is not None:
        message.text = callback

    bot_message_id = db.get_user_last_bot_message_id(user_id)
    old_message = await client.get_messages(user_id, bot_message_id)

    # SET ACCOUNT NAME BLOCK
    if re.search("wait_name", state) is not None:
        full_name = message.text
        if full_name is None or len(full_name) > 20:

            # search old message text without warning
            research = re.search(r'.*Для.*\n\nТы.*', old_message.text)
            if research is None:
                old_message_text = old_message.text
            else:
                old_message_text = research.group(0)

            # Try edit old bot message
            try:
                await Client.edit_message_text(client, user_id, bot_message_id,
                    text=old_message_text+"\n\n💢 Ой, для имени можно использовать только короткий текст 😔", reply_markup=old_message.reply_markup)
                return
            except:
                return

        db.create_account(user_id, full_name=full_name)
        db.set_state(user_id, f"create_account wait_balance {full_name}")
        await Client.edit_message_text(client, chat_id=message.chat.id, message_id=db.get_user_last_bot_message_id(user_id),
            text="☺️ Отлично! Новое имя счета - "+full_name+"\n💰 А теперь введи начальный баланс")
        logger.info(f"NAME SET SUCCESS! user_id:{user_id} full_name:{full_name}")
        
    
    if re.search("wait_balance", state) is not None:
        try:
            balance = float(message.text)
        except:
            # search old message text without warning
            research = re.search(r'.*Новое.*\nтеперь.*', old_message.text)
            if research is None:
                old_message_text = old_message.text
            else:
                old_message_text = research.group(0)
            try:
                await Client.edit_message_text(client, user_id, bot_message_id,
                    text=old_message_text+"\n\n💢 Ой,  для баланса можно использовать только цифры 😔", reply_markup=old_message.reply_markup)
                return
            except:
                return
            
        full_name = re.search(r'wait_balance.*', state).group(0)[13:]
        db.set_balance(db.get_account_id(user_id, full_name), balance)
        default = ""
        user_accounts = db.get_user_accounts(user_id)

        if len(user_accounts) < 2:
            reply_markup=InlineKeyboardMarkup([
                [InlineKeyboardButton("Меню", callback_data=f"menu")]])
            default = ", и выбран по умолчанию"
            db.set_default_account_id(user_id, user_accounts[0][0])
        else:
            reply_markup=InlineKeyboardMarkup([
                [InlineKeyboardButton("Состояние", callback_data=f"info"),
                 InlineKeyboardButton("Меню", callback_data=f"menu")]])
        db.set_state(str(user_id), "work")
        logger.info(f"BALANCE SET SUCCESS! user_id:{user_id} balance:{balance}")
        await Client.edit_message_text(client, user_id, bot_message_id, text=f"💰 Новый счет <b>{full_name}</b> с балансом <b>{balance}₽</b> успешно создан{default}.\n\n💵 Жду новых записей!\nЕсли что, вот памятка:\n[Имя счета/алиас] [+-][Сумма] [Описание]\n\nЕсли не указать имя счета, то будет использован счет по умолчанию.", reply_markup=reply_markup)\
        
# CREATE NEW TRANSACTION
async def new_transaction(client, message):
    '''
    Создает новую транзакцию
    '''
    user_id = message.chat.id
    default_account_id = db.get_user_default_account_id(user_id)
    default_account_name = db.get_account_name(default_account_id)
    account_cut = ' '
    date=message.date

    try:
        account_name = default_account_name
        research = re.match(r'\D*\s', message.text)

        if research is not None:
            account_name = research.group(0)[:-1]
            account_cut = account_name

        research = re.search(r'[-+]?\d+\.?\d?\d?', message.text)
        if research is not None:
            value = float(research.group(0))
            value_cat = research.group(0)
        
        cut_len = len(account_cut)+len(value_cat)+1
        if account_name == default_account_name:
            cut_len -= 1
        description = message.text[cut_len:]

    except:
        try:
            await Client.edit_message_text(client, user_id, db.get_user_last_bot_message_id(user_id), 
                text="💢 Ой, я не смогла понять вас 😔\nЕсли что, вот памятка:\n<b>[Имя счета/алиас] [Сумма] [Описание]</b>\n\n"+
                f"Если не указать имя счета, то будет использован <b>{default_account_name}</b>.", 
                reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Меню", callback_data=f"menu")]]))
        except:
            return
        return
    
    accounts = db.get_user_accounts(user_id)
    for account in accounts:
        aliases = str(account[3]).split(" ")
        for aliase in aliases:
            if aliase == account_name:
                account_name = account[2]

    account_id = db.get_account_id(user_id, account_name)
    if account_id is None:
        await Client.edit_message_text(client, user_id, db.get_user_last_bot_message_id(user_id), text="💢 Ой, не смогла найти такой счет 😔", 
            reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Меню", callback_data=f"menu")]]))
        return
    logger.info(f"INIT account_name={account_name} value={value} description={description} date={date}")

    balance = db.get_account_balance(account_id)
    spend_symbol = ''
    if value > 0:
        spend_symbol = '+'
    try:
        await Client.edit_message_text(client, user_id, db.get_user_last_bot_message_id(user_id), text=f"💰 <b>{account_name}: {balance}₽</b> \n\nЗначение: <b>{spend_symbol}{value}₽</b>\nОписание: <b>{description}</b>\n\nВсе верно?", 
        reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Подтвердить", callback_data=f"t-a|{account_id}|{value}|{description}"), 
                InlineKeyboardButton("Удалить", callback_data=f"transaction-delete")]]
        ))
    except:
        await Client.edit_message_text(client, user_id, db.get_user_last_bot_message_id(user_id), text=f"<b>{account_name}: {balance}₽</b> \n\nЗначение: <b>{spend_symbol}{value}₽</b>\nОписание: <b>[Слишком длинное 😔]</b>\n\nОставляем?", 
        reply_markup=InlineKeyboardMarkup([[
                InlineKeyboardButton("Подтвердить", callback_data=f"t-a|{account_id}|{value}| "), 
                InlineKeyboardButton("Удалить", callback_data=f"transaction-delete")]]
        ))
    logger.info(f"SUCCESS! user_id:{user_id} account_name:{account_name} balance:{balance} description:{description}")

# STATE HANDLER
@Client.on_message()
async def state_handler(client, message):
    '''
    Обработчик состояний. 
    Считывает состояние пользователя в момент отправки им сообщения
    и направляет на нужную функцию
    '''
    chat_id = message.chat.id
    state = db.get_state(chat_id)
    logger.info(f"Get message: user_id:{chat_id} state:{state}")

    if state == None:
        await client.send_message(chat_id, text="☺️ Привет! Для начала работы введите /start")
        return
    await Client.delete_messages(client, chat_id=chat_id, message_ids=message.id)

    # CREATE NEW ACCOUNT
    if re.search("create_account", state) is not None:
        await create_account(client, message, state)

    # CREATE NEW TRANSACTION
    if re.search("work", state) is not None:
        await new_transaction(client, message)
    
    if re.search("edit_account set_name", state) is not None:
        await set_account_name(client, message, state)

    if re.search("edit_account set_aliases", state) is not None:
        await set_account_aliases(client, message, state)

    if re.search("edit_account set_balance", state):
        await set_account_balance(client, message, state)
